﻿#if NET40 || NET461

using Apewer;
using Apewer.Internals;
using Apewer.Internals.QrCode;
using Apewer.Models;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Text;

namespace Apewer.Surface
{

    /// <summary>图像实用工具。</summary>
    public static class ImageUtility
    {

        internal static byte[] EmptyBytes { get { return new byte[0]; } }

        /// <summary>保存图像到文件。</summary>
        /// <exception cref="ArgumentNullException" />
        public static byte[] SaveAs(this Image image, ImageFormat format)
        {
            if (image == null) throw new ArgumentNullException(nameof(image));
            if (format == null) throw new ArgumentNullException(nameof(format));

            var memory = new MemoryStream();
            var bytes = null as byte[];
            try
            {
                image.Save(memory, format);
                bytes = memory.ToArray();
            }
            catch { }
            memory.Dispose();
            return bytes;
        }

        /// <summary>保存为 PNG 文件。</summary>
        /// <exception cref="ArgumentNullException" />
        public static byte[] SaveAsPng(this Image image)
        {
            return SaveAs(image, ImageFormat.Png);
        }

        /// <summary>保存为 JPEG 文件。</summary>
        /// <exception cref="ArgumentNullException" />
        public static byte[] SaveAsJpeg(this Image image)
        {
            return SaveAs(image, ImageFormat.Jpeg);
        }

        /// <summary>调整图像尺寸，生成新图像。</summary>
        /// <param name="image">原图像。</param>
        /// <param name="width">新图像的宽度，在缩放时此参数用于限定最大宽度。</param>
        /// <param name="height">新图像的高度，在缩放时此参数用于限定最大高度。</param>
        /// <param name="scale">保持原比例进行缩放。</param>
        /// <returns>新图像。</returns>
        public static Bitmap Resize(this Image image, int width, int height, bool scale = false)
        {
            if (image == null) throw new ArgumentNullException(nameof(image));
            if (width < 0) throw new ArgumentOutOfRangeException(nameof(width));
            if (height < 0) throw new ArgumentOutOfRangeException(nameof(height));

            var newWidth = width;
            var newHeight = height;
            if (scale)
            {
                newWidth = image.Width;
                newHeight = image.Height;
                var radio = Convert.ToDouble(newWidth) / Convert.ToDouble(newHeight);
                if (newWidth > width)
                {
                    newWidth = width;
                    newHeight = Convert.ToInt32(width / radio);
                }
                if (newHeight > height)
                {
                    newWidth = Convert.ToInt32(height * radio);
                    newHeight = height;
                }
            }

            var bitmap = new Bitmap(newWidth, newHeight);
            try
            {
                using (var graphic = Graphics.FromImage(bitmap))
                {
                    graphic.CompositingMode = CompositingMode.SourceOver;
                    graphic.CompositingQuality = CompositingQuality.HighQuality;
                    graphic.SmoothingMode = SmoothingMode.AntiAlias;
                    graphic.Clear(Color.Transparent);
                    graphic.DrawImage(image, 0, 0, width, height);
                }

                return bitmap;
            }
            catch (Exception ex)
            {
                RuntimeUtility.Dispose(bitmap);
                throw ex;
            }
        }

        /// <summary>生成二维码图像，可指定色块边长像素值和纠错率，失败时返回 NULL 值。</summary>
        public static Bitmap GenerateQrCode(string text, int block = 8)
        {
            return GenerateQrCode(text, block, Color.Black, Color.White);
        }

        /// <summary>生成二维码图像，可指定色块边长像素值和纠错率，失败时返回 NULL 值。</summary>
        public static Bitmap GenerateQrCode(string text, int block, Color dark, Color light)
        {
            var t = text ?? "";
            var b = block > 1 ? block : 1;
            var ecclevel = QRCodeGenerator.ECCLevel.M;

            // var ecc = QrCodeEccLevel.M;
            // if (ecc == QrCodeEccLevel.L) ecclevel = QRCodeGenerator.ECCLevel.L;
            // else if (ecc == QrCodeEccLevel.M) ecclevel = QRCodeGenerator.ECCLevel.M;
            // else if (ecc == QrCodeEccLevel.Q) ecclevel = QRCodeGenerator.ECCLevel.Q;
            // else if (ecc == QrCodeEccLevel.H) ecclevel = QRCodeGenerator.ECCLevel.H;

            try
            {
                var generator = new QRCodeGenerator();
                var content = generator.CreateQrCode(t, ecclevel);
                var qrcode = new QRCode(content);
                var bitmap = qrcode.GetGraphic(b, dark, light, false);
                return bitmap;
            }
            catch { return null; }
        }

        /// <summary>从 RGBA 十六进制字符串获取颜色。</summary>
        public static Color GetColorByHex(string hex, Color @default)
        {
            var lower = hex.ToLower();
            if (lower == "none" || lower == "alpha" || lower == "transparent")
            {
                return Color.Transparent;
            }
            else
            {
                const string pool = "0123456789abcdef";
                lower = TextUtility.Restrict(lower, pool);
                if (lower.Length >= 6)
                {
                    var r = pool.IndexOf(lower[0]) * 16 + pool.IndexOf(lower[1]);
                    var g = pool.IndexOf(lower[2]) * 16 + pool.IndexOf(lower[3]);
                    var b = pool.IndexOf(lower[4]) * 16 + pool.IndexOf(lower[5]);
                    var a = 255;
                    if (lower.Length >= 8)
                    {
                        a = pool.IndexOf(lower[6]) * 16 + pool.IndexOf(lower[7]);
                    }
                    var color = Color.FromArgb(a, r, g, b);
                    return color;
                }
            }
            return @default;
        }

    }

}

#endif
